package com.jdd.config.mqtt;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jdd.common.constant.CacheConstant;
import com.jdd.common.constant.JddConstant;
import com.jdd.common.util.AsynRestTmplateUtils;
import com.jdd.common.util.CacheUtil;
import com.jdd.modules.operationLog.service.IParkHandOverLogService;
import com.jdd.modules.order.entity.ParkOrderInfo;
import com.jdd.modules.order.service.IParkOrderInfoService;
import com.jdd.modules.order.service.MqttClientMsgProcessService;
import com.jdd.modules.parking.mapper.ParkCarEnterLogMapper;
import com.jdd.modules.parking.mapper.ParkCarOutLogMapper;
import com.jdd.modules.parking.service.IParkArmInfoService;
import com.jdd.modules.parking.service.IParkCarOutEntranceRecordService;
import com.jdd.modules.parking.service.IParkWorkStationService;
import com.jdd.modules.parking.service.IparkCarEnterLogService;
import com.jdd.modules.sdk.LedCallInterface;
import com.jdd.modules.sdkidentifyresultpushlog.entity.SdkIdentifyResultPushLog;
import com.jdd.modules.sdkidentifyresultpushlog.service.ISdkIdentifyResultPushLogV3Service;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.iot.mqtt.spring.client.MqttClientSubscribe;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.tio.utils.buffer.ByteBufferUtil;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;


@Slf4j
@Service
public class MqttClientSubscribeListener {

    @Autowired
    MqttClientMsgProcessService mqttClientMsgProcessService;

    @Resource
    IParkOrderInfoService parkOrderInfoService;
    @Resource
    CacheUtil cacheUtil;
    @Resource
    ISdkIdentifyResultPushLogV3Service sdkIdentifyResultPushLogV3Service;
    @Resource
    IParkArmInfoService parkArmInfoService;
    @Resource
    IParkCarOutEntranceRecordService parkCarOutEntranceRecordService;
    @Resource
    ParkCarOutLogMapper parkCarOutLogMapper;
    @Resource
    ParkCarEnterLogMapper parkCarEnterLogMapper;
    @Resource
    AsynRestTmplateUtils asynRestTmplateUtils;
    @Resource
    IParkWorkStationService parkWorkStationService;
    @Resource
    IParkHandOverLogService parkHandOverLogService;
    @Resource
    LedCallInterface ledCallInterface;
    @Resource
    IparkCarEnterLogService parkCarEnterLogService;


    // @MqttClientSubscribe("test/#")
    // public void subQos0(String topic, ByteBuffer payload) {
    //     String s = ByteBufferUtil.toString(payload);
    //     logger.info("topic:{} payload:{}", topic, s);
    //     mqttClientMsgProcessService.processMsg(s);
    // }

    // @MqttClientSubscribe(value = "qos1/#", qos = MqttQoS.AT_LEAST_ONCE)
    // public void subQos1(String topic, ByteBuffer payload) {
    //     logger.info("topic:{} payload:{}", topic, ByteBufferUtil.toString(payload));
    // }

    /**
     * 处理支付结果
     *
     * @param topic
     * @param payload
     */
    @Async
    @MqttClientSubscribe("parking/${parkInfo.parkCode}/parkOrderInfo/payInfo")
    public void payInfo(String topic, ByteBuffer payload) throws IOException {
        // 1.3.8 开始支持，@MqttClientSubscribe 注解支持 ${} 变量替换，会默认替换成 +
        // 注意：mica-mqtt 会先从 Spring boot 配置中替换参数 ${}，如果存在配置会优先被替换。
        //解析参数
        String mqttResult = ByteBufferUtil.toString(payload);
        log.info("topic:{} payload:{}", topic, mqttResult);
        JSONObject mqttJson = JSONUtil.parseObj(mqttResult);
        JSONObject parkOrderInfoJson = mqttJson.getJSONObject("parkOrderInfo");
        ParkOrderInfo parkOrderInfo = BeanUtil.toBean(parkOrderInfoJson, ParkOrderInfo.class);

        //查询订单信息
        LambdaQueryWrapper<ParkOrderInfo> query = new LambdaQueryWrapper<>();
        query.eq(ParkOrderInfo::getOrderId, parkOrderInfo.getOrderId())
                .eq(ParkOrderInfo::getOrderStatus, JddConstant.OrderConstant.ORDER_PAY_STATE_UNPAID);
        List<ParkOrderInfo> orderInfos = parkOrderInfoService.list(query);
        if (CollUtil.isEmpty(orderInfos)) {
            log.error("没有找到账单信息");
            return;
        }

        //更新订单信息
        ParkOrderInfo orderInfo = orderInfos.get(0);
        orderInfo.setOrderId(parkOrderInfo.getOrderId());
        orderInfo.setOutTradeNo(parkOrderInfo.getOutTradeNo());
        orderInfo.setOrderStatus(JddConstant.OrderConstant.ORDER_PAY_STATE_SUCCESS);
        boolean b = parkOrderInfoService.updateById(orderInfo);
        if (!b) {
            return;
        }


        //开闸
        //获取当前出口闸机是否有等待车辆，如果有再支付完成后需要开闸
        String currentOutCacheCarInfo = cacheUtil.get(CacheConstant.CURRENT_EXIT_LICENSE_PLATE, orderInfo.getSerialNo());
        //当前出口没有缓存车牌信息；如果没有缓存信息为场内支付
        if (StrUtil.isBlank(currentOutCacheCarInfo)) {
            return;
        }
        String[] outCarInfo = currentOutCacheCarInfo.split("#");
        String license = outCarInfo[0];
        String ossImg = outCarInfo[1];
        String img = outCarInfo[2];
        String armName = outCarInfo[3];
        //有缓存，车牌不匹配算场内支付
        if (!orderInfo.getPlateNo().equals(license)) {
            return;
        }

        //给当前车辆开闸
        try {
            ledCallInterface.OutPayParkingFeeAll(orderInfo.getSerialNo(), license);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        //保存入场记录
        SdkIdentifyResultPushLog pushLog = new SdkIdentifyResultPushLog();
        pushLog.setParkCode(orderInfo.getParkCode());
        pushLog.setLicense(orderInfo.getPlateNo());
        pushLog.setImg(img);
        pushLog.setOssImg(ossImg);
        pushLog.setSerialNo(orderInfo.getSerialNo());
        sdkIdentifyResultPushLogV3Service.handle(pushLog, null);
    }

    /**
     * 下订单同步到场端保存
     *
     * @param topic
     * @param payload
     */
    @Async
    @MqttClientSubscribe("parking/${parkInfo.parkCode}/parkOrderInfo/orderInfo")
    public void orderInfo(String topic, ByteBuffer payload) {
        log.info("开始处理订单结果开始");
        String mqttResult = ByteBufferUtil.toString(payload);
        log.info("topic:{} payload:{}", topic, mqttResult);

        if (StrUtil.isBlank(mqttResult)) {
            return;
        }

        JSONObject mqttJson = JSONUtil.parseObj(mqttResult);
        JSONObject parkOrderInfoJson = mqttJson.getJSONObject("parkOrderInfo");
        ParkOrderInfo parkOrderInfo = JSONUtil.toBean(parkOrderInfoJson, ParkOrderInfo.class);

        //如果数据库存在数据则修改；反之新增
        ParkOrderInfo parkOrderInfo1 = parkOrderInfoService.getById(parkOrderInfo.getId());
        if (parkOrderInfo1 != null) {
            if (JddConstant.OrderConstant.ORDER_PAY_STATE_UNPAID.equals(parkOrderInfo1.getOrderStatus())) {
                BeanUtil.copyProperties(parkOrderInfo, parkOrderInfo1);
                parkOrderInfoService.updateById(parkOrderInfo1);
            }
        } else {
            parkOrderInfoService.save(parkOrderInfo);
        }
    }

}
